#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/can.h>
#include <linux/can/raw.h>

#define DEV_PATH "/dev/pcie_cdev_canfd"

// 匹配驱动中的结构体定义
typedef struct {
    unsigned char fmt;          // 0:标准帧; 1:扩展帧
    unsigned char rtr;          // 0:数据帧; 1:远程帧
    unsigned long id;           // 报文ID
    unsigned char dlc;          // 数据长度(0-64)
    unsigned char flg;          // CANFD标志(0:CAN, 1:CANFD)
    unsigned char data[64];     // 载荷数据
} canfd_msg_t;

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <read|write>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int fd = open(DEV_PATH, O_RDWR);
    if (fd < 0) {
        perror("Failed to open device");
        exit(EXIT_FAILURE);
    }

    if (strcmp(argv[1], "write") == 0) {
        // 准备测试CAN FD帧
        canfd_msg_t tx_frame = {
            .fmt = 1,          // 扩展帧
            .rtr = 0,          // 数据帧
            .id = 0x18FF34F1,  // 扩展ID示例
            .dlc = 16,         // 16字节数据
            .flg = 1           // CAN FD帧
        };
        
        // 填充测试数据
        for (int i = 0; i < tx_frame.dlc; i++) {
            tx_frame.data[i] = i;
        }

        ssize_t bytes_written = write(fd, &tx_frame, sizeof(tx_frame));
        if (bytes_written < 0) {
            perror("Write failed");
            close(fd);
            exit(EXIT_FAILURE);
        }
        printf("Written %zd bytes: ID=0x%lX DLC=%d\n", 
               bytes_written, tx_frame.id, tx_frame.dlc);

    } else if (strcmp(argv[1], "read") == 0) {
        canfd_msg_t rx_frame;
        
        printf("Waiting for CAN FD frame...\n");
        ssize_t bytes_read = read(fd, &rx_frame, sizeof(rx_frame));
        if (bytes_read < 0) {
            perror("Read failed");
            close(fd);
            exit(EXIT_FAILURE);
        }

        // 打印接收到的帧信息
        printf("Received %zd bytes:\n", bytes_read);
        printf("Frame Type: %s\n", rx_frame.fmt ? "Extended" : "Standard");
        printf("Frame Format: %s\n", rx_frame.rtr ? "Remote" : "Data");
        printf("CAN FD: %s\n", rx_frame.flg ? "YES" : "NO");
        printf("ID: 0x%lX\n", rx_frame.id);
        printf("DLC: %d\n", rx_frame.dlc);
        
        printf("Data: ");
        for (int i = 0; i < rx_frame.dlc; i++) {
            printf("%02X ", rx_frame.data[i]);
        }
        printf("\n");

    } else {
        fprintf(stderr, "Invalid command: %s\n", argv[1]);
        close(fd);
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}
